package org.loong.crypto.extension.cms.jce;

import java.security.PublicKey;
import java.security.cert.X509Certificate;

import org.bouncycastle.cms.CMSSignatureAlgorithmNameGenerator;
import org.bouncycastle.cms.DefaultCMSSignatureAlgorithmNameGenerator;
import org.bouncycastle.cms.SignerInformationVerifier;
import org.bouncycastle.operator.ContentVerifierProvider;
import org.bouncycastle.operator.DefaultSignatureAlgorithmIdentifierFinder;
import org.bouncycastle.operator.DigestCalculatorProvider;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.operator.SignatureAlgorithmIdentifierFinder;
import org.loong.crypto.extension.operator.jce.JceContentVerifierProviderBuilder;
import org.loong.crypto.service.CryptoService;

public class JceSignerInfoVerifierBuilder {

    private Helper helper = new Helper();
    
    private DigestCalculatorProvider digestProvider;
    
    private CMSSignatureAlgorithmNameGenerator sigAlgNameGen = new DefaultCMSSignatureAlgorithmNameGenerator();
    
    private SignatureAlgorithmIdentifierFinder sigAlgIDFinder = new DefaultSignatureAlgorithmIdentifierFinder();

    public JceSignerInfoVerifierBuilder(DigestCalculatorProvider digestProvider) {
        this.digestProvider = digestProvider;
    }

    /**
     * Override the default signature algorithm name generator.
     *
     * @param sigAlgNameGen the algorithm name generator to use.
     * @return the current builder.
     */
    public JceSignerInfoVerifierBuilder setSignatureAlgorithmNameGenerator(CMSSignatureAlgorithmNameGenerator sigAlgNameGen) {
        this.sigAlgNameGen = sigAlgNameGen;
        return this;
    }

    public JceSignerInfoVerifierBuilder setSignatureAlgorithmFinder(SignatureAlgorithmIdentifierFinder sigAlgIDFinder) {
        this.sigAlgIDFinder = sigAlgIDFinder;
        return this;
    }

    public SignerInformationVerifier build(CryptoService cryptoService, X509Certificate certificate) throws OperatorCreationException {
        return new SignerInformationVerifier(sigAlgNameGen, sigAlgIDFinder, helper.createContentVerifierProvider(cryptoService, certificate), digestProvider);
    }

    public SignerInformationVerifier build(CryptoService cryptoService, PublicKey publicKey) throws OperatorCreationException {
        return new SignerInformationVerifier(sigAlgNameGen, sigAlgIDFinder, helper.createContentVerifierProvider(cryptoService, publicKey), digestProvider);
    }

    private class Helper {

        ContentVerifierProvider createContentVerifierProvider(CryptoService cryptoService, PublicKey publicKey) throws OperatorCreationException {
            return new JceContentVerifierProviderBuilder(cryptoService).build(publicKey);
        }

        ContentVerifierProvider createContentVerifierProvider(CryptoService cryptoService, X509Certificate certificate) throws OperatorCreationException {
            return new JceContentVerifierProviderBuilder(cryptoService).build(certificate.getPublicKey());
        }
    }
}
